package com.obggtc.picture.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.obggtc.picture.common.R;
import com.obggtc.picture.config.PathConfig;
import com.obggtc.picture.entity.MediaFile;
import com.obggtc.picture.service.MediaFileService;
import com.obggtc.picture.utils.*;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 视频控制器
 */
@RestController
@RequestMapping("/video")
@CrossOrigin
@PreAuthorize("isAuthenticated()")
public class VideoController {

    private static final Logger log = LoggerFactory.getLogger(VideoController.class);

    @Autowired
    private PathConfig pathConfig;

    @Autowired
    private VideoCacheUtils videoCacheUtils;

    @Autowired
    private RedisLockUtils redisLockUtils;

    @Autowired
    private RedisRateLimiterUtils rateLimiterUtils;

    @Autowired
    private MediaFileService mediaFileService;

    // 支持的视频格式
    private static final Set<String> ALLOWED_VIDEO_TYPES = new HashSet<>(Arrays.asList(
            "video/mp4", "video/avi", "video/mov", "video/wmv", "video/flv",
            "video/webm", "video/mkv", "video/3gp", "video/m4v"
    ));

    // 支持的视频文件扩展名
    private static final Set<String> ALLOWED_VIDEO_EXTENSIONS = new HashSet<>(Arrays.asList(
            ".mp4", ".avi", ".mov", ".wmv", ".flv", ".webm", ".mkv", ".3gp", ".m4v"
    ));

    // 最大文件大小 (100MB)
    private static final long MAX_FILE_SIZE = 100 * 1024 * 1024;

    /**
     * 上传视频
     * @param file 视频文件
     * @param title 视频标题
     * @param description 视频描述
     * @param tags 视频标签（逗号分隔）
     * @return 上传结果
     */
    @SneakyThrows
    @PostMapping("/upload")
    public R<Map<String, Object>> uploadVideo(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "title", required = false) String title,
            @RequestParam(value = "description", required = false) String description,
            @RequestParam(value = "tags", required = false) String tags,
            HttpServletRequest request) {

        // 获取当前用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();

        // 1. 基本参数验证
        if (file.isEmpty()) {
            return R.failed("视频文件不能为空");
        }

        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null) {
            return R.failed("文件名不能为空");
        }

        // 2. 文件类型验证
        String contentType = file.getContentType();
        String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();

        if (!ALLOWED_VIDEO_TYPES.contains(contentType) && !ALLOWED_VIDEO_EXTENSIONS.contains(fileExtension)) {
            return R.failed("不支持的视频格式，支持的格式：MP4、AVI、MOV、WMV、FLV、WebM、MKV、3GP、M4V");
        }

        // 3. 文件大小验证
        if (file.getSize() > MAX_FILE_SIZE) {
            return R.failed("视频文件大小不能超过100MB");
        }

        // 4. 限流检查
        if (!rateLimiterUtils.isUploadAllowed(username, 10, 3600)) {
            return R.failed("上传频率过高，每小时最多上传10个视频，请稍后再试");
        }

        // 5. 获取上传锁
        String lockValue = redisLockUtils.tryFileUploadLock(originalFilename);
        if (lockValue == null) {
            return R.failed("该视频文件正在被其他用户上传，请稍后再试");
        }

        try {
            // 6. 生成新文件名和视频ID
            String videoId = "video_" + System.currentTimeMillis() + "_" + StringTool.getUUID();
            String newFileName = videoId + fileExtension;

            // 7. 确定保存路径
            File videoFile;
            File videoDir;
            String host;
            String filePath;
            String os = System.getProperty("os.name");

            if (os.toLowerCase().startsWith("win")) {
                host = pathConfig.getWinHost();
                videoFile = new File(pathConfig.getWinVideoPath(), newFileName);
                videoDir = new File(pathConfig.getWinVideoPath());
                filePath = pathConfig.getWinVideoPath();
            } else {
                host = pathConfig.getLinuxHost();
                videoFile = new File(pathConfig.getLinuxVideoPath(), newFileName);
                videoDir = new File(pathConfig.getLinuxVideoPath());
                filePath = pathConfig.getLinuxVideoPath();
            }

            // 8. 创建目录
            if (!videoDir.exists()) {
                boolean created = videoDir.mkdirs();
                if (!created) {
                    log.error("创建视频目录失败: {}", videoDir.getAbsolutePath());
                    return R.failed("创建视频目录失败");
                }
            }

            // 9. 设置上传状态
            videoCacheUtils.setProcessingStatus(videoId, "uploading", 0);

            // 10. 保存文件
            file.transferTo(videoFile);
            log.info("视频文件保存成功: {}", videoFile.getAbsolutePath());

            // 11. 生成可访问的绝对URL（优先使用请求头推断出的外网地址，回退到配置host）
            String baseHost = resolveBaseHost(request, host);
            String videoUrl = baseHost + "/static/video/" + newFileName;

            // 12. 生成视频缩略图（智能降级方案）
            String thumbnailUrl = null;
            try {
                File thumbsDir = new File(videoDir, "thumbs");
                if (!thumbsDir.exists()) {
                    boolean mkThumbs = thumbsDir.mkdirs();
                    log.info("创建缩略图目录 {} -> {}", thumbsDir.getAbsolutePath(), mkThumbs);
                }
                File thumbFile = new File(thumbsDir, videoId + ".jpg");

                // 智能缩略图生成：优先FFmpeg，降级到Java原生
                if (generateSmartThumbnail(videoFile, thumbFile)) {
                    thumbnailUrl = baseHost + "/static/video/thumbs/" + thumbFile.getName();
                    log.info("视频缩略图生成成功: {}", thumbnailUrl);
                } else {
                    log.warn("视频缩略图生成失败: {}", thumbFile.getAbsolutePath());
                }
            } catch (Exception ex) {
                log.warn("生成视频缩略图发生异常: {}", ex.getMessage());
            }

            // 13. 保存到数据库
            MediaFile mediaFile = new MediaFile();
            mediaFile.setFileId(videoId);
            mediaFile.setFileType(MediaFile.FILE_TYPE_VIDEO);
            mediaFile.setOriginalFilename(originalFilename);
            mediaFile.setStoredFilename(newFileName);
            mediaFile.setFileSize(file.getSize());
            mediaFile.setFilePath(filePath);
            mediaFile.setFileUrl(videoUrl);
            mediaFile.setMimeType(contentType);
            mediaFile.setFileExtension(fileExtension);
            if (thumbnailUrl != null) {
                mediaFile.setThumbnailUrl(thumbnailUrl);
            }
            mediaFile.setTitle(title != null ? title : originalFilename);
            mediaFile.setDescription(description != null ? description : "");
            mediaFile.setTags(tags);
            mediaFile.setViewCount(0L);
            mediaFile.setDownloadCount(0L);
            mediaFile.setStatus(MediaFile.STATUS_NORMAL);
            mediaFile.setIsPublic(MediaFile.PRIVACY_PUBLIC);
            mediaFile.setUploader(username);
            mediaFile.setUploaderIp(getClientIpAddress(request));
            mediaFile.setCreateTime(LocalDateTime.now());
            mediaFile.setUploadTime(LocalDateTime.now());

            // 保存到数据库
            boolean saved = mediaFileService.saveMediaFile(mediaFile);
            if (!saved) {
                log.error("保存视频信息到数据库失败: {}", videoId);
                return R.failed("保存视频信息失败");
            }

            // 手动清除相关缓存，确保新上传的视频能立即在列表中显示
            mediaFileService.clearMediaFileCache(videoId);

            // 14. 缓存视频基本信息（保留Redis缓存以提高性能）
            Map<String, Object> videoInfo = new HashMap<>();
            videoInfo.put("videoId", videoId);
            videoInfo.put("fileName", originalFilename);
            videoInfo.put("newFileName", newFileName);
            videoInfo.put("fileSize", file.getSize());
            videoInfo.put("fileType", contentType);
            videoInfo.put("uploader", username);
            videoInfo.put("uploadTime", System.currentTimeMillis());
            videoInfo.put("title", title != null ? title : originalFilename);
            videoInfo.put("description", description != null ? description : "");
            videoInfo.put("videoUrl", videoUrl);
            if (thumbnailUrl != null) {
                videoInfo.put("thumbnailUrl", thumbnailUrl);
            }

            videoCacheUtils.cacheVideoInfo(videoId, videoInfo);

            // 15. 添加到用户视频列表（Redis缓存）
            videoCacheUtils.addUserVideo(username, videoId);

            // 16. 添加到最近上传列表（Redis缓存）
            videoCacheUtils.addToRecentUploads(videoId);

            // 17. 处理标签
            if (tags != null && !tags.trim().isEmpty()) {
                List<String> tagList = Arrays.asList(tags.split(","));
                // 清理标签（去除空格）
                tagList = tagList.stream()
                        .map(String::trim)
                        .filter(tag -> !tag.isEmpty())
                        .collect(java.util.stream.Collectors.toList());

                videoCacheUtils.cacheVideoTags(videoId, tagList);

                // 为每个标签添加视频
                for (String tag : tagList) {
                    videoCacheUtils.addVideoToTag(tag, videoId);
                }
            }

            // 18. 更新处理状态
            videoCacheUtils.setProcessingStatus(videoId, "completed", 100);

            // 19. 返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("videoId", videoId);
            result.put("videoUrl", videoUrl);
            if (thumbnailUrl != null) {
                result.put("thumbnailUrl", thumbnailUrl);
            }
            result.put("fileName", originalFilename);
            result.put("fileSize", file.getSize());
            result.put("uploadTime", System.currentTimeMillis());

            log.info("视频上传成功 - 用户: {}, 视频ID: {}, 文件名: {}", username, videoId, originalFilename);

            return R.ok(result, "视频上传成功");

        } catch (Exception e) {
            log.error("视频上传失败", e);
            return R.failed("视频上传失败: " + e.getMessage());
        } finally {
            // 19. 释放锁
            redisLockUtils.unlock("file:upload:" + originalFilename, lockValue);
        }
    }

    /**
     * 获取用户的视频列表
     * @param page 页码（默认1）
     * @param size 每页大小（默认10）
     * @return 视频列表
     */
    @GetMapping("/list")
    public R<Map<String, Object>> getUserVideos(
            @RequestParam(value = "page", defaultValue = "1") int page,
            @RequestParam(value = "size", defaultValue = "10") int size) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();

        try {
            log.info("开始获取用户视频列表 - username: {}, page: {}, size: {}", username, page, size);

            // 先统计总数
            long totalCount = mediaFileService.countUserMediaFiles(username, MediaFile.FILE_TYPE_VIDEO);
            log.info("用户视频总数 - username: {}, totalCount: {}", username, totalCount);

            // 使用新的数据库服务查询（带缓存）
            IPage<MediaFile> result = mediaFileService.getUserMediaFiles(username, MediaFile.FILE_TYPE_VIDEO, page, size);

            Map<String, Object> response = new HashMap<>();
            response.put("videos", result.getRecords());
            response.put("total", result.getTotal());
            response.put("page", result.getCurrent());
            response.put("size", result.getSize());
            response.put("totalPages", result.getPages());

            log.info("返回视频列表响应 - username: {}, total: {}, records: {}", username, result.getTotal(), result.getRecords().size());
            return R.ok(response, "获取视频列表成功");
        } catch (Exception e) {
            log.error("获取用户视频列表失败", e);
            return R.failed("获取视频列表失败");
        }
    }

    /**
     * 获取视频详细信息
     * @param videoId 视频ID
     * @return 视频详细信息
     */
    @GetMapping("/{videoId}")
    public R<MediaFile> getVideoDetail(@PathVariable String videoId) {
        try {
            MediaFile mediaFile = mediaFileService.getMediaFileByFileId(videoId);

            if (mediaFile == null || !(MediaFile.FILE_TYPE_VIDEO == mediaFile.getFileType())) {
                return R.failed("视频不存在");
            }

            // 增加观看次数
            long viewCount = mediaFileService.incrementViewCount(videoId);
            mediaFile.setViewCount(viewCount);

            return R.ok(mediaFile, "获取视频详情成功");
        } catch (Exception e) {
            log.error("获取视频详情失败: {}", videoId, e);
            return R.failed("获取视频详情失败");
        }
    }

    /**
     * 删除视频
     * @param videoId 视频ID
     * @return 删除结果
     */
    @DeleteMapping("/{videoId}")
    public R<String> deleteVideo(@PathVariable String videoId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();

        try {
            // 使用新的服务删除视频（包含权限验证和物理文件删除）
            boolean success = mediaFileService.deleteMediaFile(videoId, username);
            if (success) {
                // 清除所有相关缓存
                videoCacheUtils.clearAllVideoCache(videoId);

                // 从用户视频列表中移除
                videoCacheUtils.removeUserVideo(username, videoId);

                log.info("视频删除成功 - 用户: {}, 视频ID: {}", username, videoId);
                return R.ok("视频删除成功");
            } else {
                return R.failed("视频删除失败");
            }
        } catch (Exception e) {
            log.error("删除视频失败: {}", videoId, e);
            return R.failed("删除视频失败: " + e.getMessage());
        }
    }

    /**
     * 获取最近上传的视频
     * @param count 返回数量（默认10）
     * @return 最近上传的视频列表
     */
    @GetMapping("/recent")
    public R<List<MediaFile>> getRecentVideos(@RequestParam(value = "count", defaultValue = "10") int count) {
        try {
            List<MediaFile> recentVideos = mediaFileService.getRecentMediaFiles(MediaFile.FILE_TYPE_VIDEO, count);
            return R.ok(recentVideos, "获取最近上传视频成功");
        } catch (Exception e) {
            log.error("获取最近上传视频失败", e);
            return R.failed("获取最近上传视频失败");
        }
    }

    /**
     * 根据标签搜索视频
     * @param tag 标签
     * @param page 页码（默认1）
     * @param size 每页大小（默认10）
     * @return 搜索结果
     */
    @GetMapping("/search/tag")
    public R<Map<String, Object>> searchVideosByTag(
            @RequestParam("tag") String tag,
            @RequestParam(value = "page", defaultValue = "1") int page,
            @RequestParam(value = "size", defaultValue = "10") int size) {

        try {
            IPage<MediaFile> result = mediaFileService.getMediaFilesByTag(tag, MediaFile.FILE_TYPE_VIDEO, page, size);

            Map<String, Object> response = new HashMap<>();
            response.put("videos", result.getRecords());
            response.put("total", result.getTotal());
            response.put("page", result.getCurrent());
            response.put("size", result.getSize());
            response.put("tag", tag);

            return R.ok(response, "搜索视频成功");
        } catch (Exception e) {
            log.error("搜索视频失败", e);
            return R.failed("搜索视频失败");
        }
    }

    /**
     * 获取视频处理状态
     * @param videoId 视频ID
     * @return 处理状态
     */
    @GetMapping("/{videoId}/status")
    public R<Map<Object, Object>> getProcessingStatus(@PathVariable String videoId) {
        Map<Object, Object> status = videoCacheUtils.getProcessingStatus(videoId);

        if (status == null || status.isEmpty()) {
            return R.failed("视频处理状态不存在");
        }

        return R.ok(status, "获取处理状态成功");
    }

    /**
     * 获取客户端真实IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {
            return xForwardedFor.split(",")[0].trim();
        }

        String xRealIp = request.getHeader("X-Real-IP");
        if (xRealIp != null && !xRealIp.isEmpty() && !"unknown".equalsIgnoreCase(xRealIp)) {
            return xRealIp;
        }

        return request.getRemoteAddr();
    }

    /**
     * 从请求中解析对外可访问的Host（优先 X-Forwarded-Proto/Host，其次 Referer，最后回退到配置host）
     */
    private String resolveBaseHost(HttpServletRequest request, String fallbackHost) {
        try {
            String scheme = Optional.ofNullable(request.getHeader("X-Forwarded-Proto")).orElse(request.getScheme());
            String host = Optional.ofNullable(request.getHeader("X-Forwarded-Host")).orElse(request.getHeader("Host"));
            if (host != null && !host.isEmpty()) {
                return scheme + "://" + host;
            }
            String referer = request.getHeader("Referer");
            if (referer != null && referer.startsWith("http")) {
                // 取 referer 的协议+主机
                try {
                    java.net.URI uri = new java.net.URI(referer);
                    return uri.getScheme() + "://" + uri.getHost() + (uri.getPort() > 0 ? (":" + uri.getPort()) : "");
                } catch (Exception ignore) {}
            }
        } catch (Exception e) {
            log.debug("resolveBaseHost 异常: {}", e.getMessage());
        }
        return fallbackHost;
    }

    /**
     * 使用本机已安装的 ffmpeg 从视频中截取缩略图
     * 要求：服务器已安装 ffmpeg 并在 PATH 可执行
     * 策略：
     * - 优先在 1 秒处抽帧（-ss 1），若失败再退回 0 秒处
     * - 输出 JPEG，质量 q=2（高质量）
     */
    private boolean generateVideoThumbnail(File videoFile, File outputImageFile) {
        try {
            // 优先 1 秒抽帧
            String[] cmd1 = new String[]{
                    "ffmpeg", "-y", "-ss", "00:00:01",
                    "-i", videoFile.getAbsolutePath(),
                    "-frames:v", "1",
                    "-q:v", "2",
                    outputImageFile.getAbsolutePath()
            };
            int code1 = runProcess(cmd1, 20);
            if (code1 == 0 && outputImageFile.exists() && outputImageFile.length() > 0) {
                return true;
            }

            // 回退 0 秒抽帧
            String[] cmd2 = new String[]{
                    "ffmpeg", "-y",
                    "-i", videoFile.getAbsolutePath(),
                    "-frames:v", "1",
                    "-q:v", "2",
                    outputImageFile.getAbsolutePath()
            };
            int code2 = runProcess(cmd2, 20);
            return code2 == 0 && outputImageFile.exists() && outputImageFile.length() > 0;
        } catch (Exception e) {
            log.warn("ffmpeg 生成缩略图异常: {}", e.getMessage());
            return false;
        }
    }

    private int runProcess(String[] command, int timeoutSeconds) throws Exception {
        ProcessBuilder pb = new ProcessBuilder(command);
        pb.redirectErrorStream(true);
        Process proc = pb.start();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                log.debug("ffmpeg> {}", line);
            }
        }
        if (!proc.waitFor(timeoutSeconds, java.util.concurrent.TimeUnit.SECONDS)) {
            proc.destroyForcibly();
            return -1;
        }
        return proc.exitValue();
    }

    /**
     * 智能缩略图生成：优先使用FFmpeg，不可用时降级到Java原生方案
     * @param videoFile 视频文件
     * @param outputImageFile 输出缩略图文件
     * @return 是否成功生成缩略图
     */
    private boolean generateSmartThumbnail(File videoFile, File outputImageFile) {

        boolean res = VideoUtils.generateSmartThumbnail(videoFile, outputImageFile);

        if (res) return true;

        // 方案1：尝试使用FFmpeg生成真实缩略图
        if (isFFmpegAvailable() && generateVideoThumbnail(videoFile, outputImageFile)) {
            log.info("使用FFmpeg生成缩略图成功");
            return true;
        }

        // 方案2：FFmpeg不可用，使用Java原生生成美观缩略图
        log.info("FFmpeg不可用，使用Java原生方案生成缩略图");
        return generateJavaThumbnail(videoFile, outputImageFile);
    }

    /**
     * 检查FFmpeg是否可用
     * @return true如果FFmpeg可用，false否则
     */
    private boolean isFFmpegAvailable() {
        try {
            ProcessBuilder pb = new ProcessBuilder("ffmpeg", "-version");
            pb.redirectErrorStream(true);
            Process proc = pb.start();

            boolean finished = proc.waitFor(3, java.util.concurrent.TimeUnit.SECONDS);
            if (finished && proc.exitValue() == 0) {
                log.debug("FFmpeg可用");
                return true;
            } else {
                log.warn("FFmpeg检查失败，退出码: {}", finished ? proc.exitValue() : "超时");
                return false;
            }
        } catch (Exception e) {
            log.warn("FFmpeg不可用: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 使用Java原生API生成美观的视频缩略图
     * @param videoFile 视频文件
     * @param outputImageFile 输出缩略图文件
     * @return 是否成功生成
     */
    private boolean generateJavaThumbnail(File videoFile, File outputImageFile) {
        try {
            // 创建320x240的缩略图画布
            java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(320, 240, java.awt.image.BufferedImage.TYPE_INT_RGB);
            java.awt.Graphics2D g2d = image.createGraphics();

            // 开启抗锯齿
            g2d.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            // 创建渐变背景
            java.awt.GradientPaint gradient = new java.awt.GradientPaint(
                    0, 0, new java.awt.Color(52, 152, 219),      // 蓝色渐变起始
                    320, 240, new java.awt.Color(41, 128, 185)   // 蓝色渐变结束
            );
            g2d.setPaint(gradient);
            g2d.fillRect(0, 0, 320, 240);

            // 绘制中央播放按钮
            int centerX = 160, centerY = 120;

            // 外层白色圆形背景
            g2d.setColor(java.awt.Color.WHITE);
            g2d.fillOval(centerX - 40, centerY - 40, 80, 80);

            // 内层播放三角形
            g2d.setColor(new java.awt.Color(52, 152, 219));
            int[] xPoints = {centerX - 15, centerX + 20, centerX - 15};
            int[] yPoints = {centerY - 18, centerY, centerY + 18};
            g2d.fillPolygon(xPoints, yPoints, 3);

            // 绘制文件信息
            g2d.setColor(java.awt.Color.WHITE);

            // 文件名（截断过长的名称）
            String fileName = videoFile.getName();
            if (fileName.length() > 28) {
                fileName = fileName.substring(0, 25) + "...";
            }

            g2d.setFont(new java.awt.Font("Microsoft YaHei", java.awt.Font.BOLD, 14));
            java.awt.FontMetrics fm = g2d.getFontMetrics();
            int textWidth = fm.stringWidth(fileName);
            g2d.drawString(fileName, (320 - textWidth) / 2, centerY + 65);

            // 文件大小
            String fileSize = formatFileSize(videoFile.length());
            g2d.setFont(new java.awt.Font("Microsoft YaHei", java.awt.Font.PLAIN, 12));
            fm = g2d.getFontMetrics();
            textWidth = fm.stringWidth(fileSize);
            g2d.drawString(fileSize, (320 - textWidth) / 2, centerY + 85);

            // 视频标识
            g2d.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 10));
            String videoLabel = "VIDEO";
            fm = g2d.getFontMetrics();
            textWidth = fm.stringWidth(videoLabel);
            g2d.drawString(videoLabel, (320 - textWidth) / 2, centerY + 105);

            g2d.dispose();

            // 保存为JPEG格式
            boolean saved = javax.imageio.ImageIO.write(image, "jpg", outputImageFile);
            if (saved) {
                log.info("Java原生缩略图生成成功: {}", outputImageFile.getAbsolutePath());
                return true;
            } else {
                log.warn("保存缩略图文件失败");
                return false;
            }

        } catch (Exception e) {
            log.error("Java原生缩略图生成失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 格式化文件大小为人类可读格式
     * @param bytes 字节数
     * @return 格式化后的文件大小字符串
     */
    private String formatFileSize(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return String.format("%.1f KB", bytes / 1024.0);
        } else if (bytes < 1024 * 1024 * 1024) {
            return String.format("%.1f MB", bytes / (1024.0 * 1024));
        } else {
            return String.format("%.1f GB", bytes / (1024.0 * 1024 * 1024));
        }
    }
} 